﻿using InfoPathDebugger.RuleManager;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.XPath;
using System.Xml.Linq;
using System.IO;
using System.Xml;
using InfoPathDebugger;

namespace RuleManagerTest
{
    
    
    /// <summary>
    ///This is a test class for RuleManagerTest and is intended
    ///to contain all RuleManagerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class RuleManagerTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        #region ExecuteRule Tests

        /// <summary>
        ///A test for ExecuteRule when the rule is disabled.
        ///</summary>
        [TestMethod()]
        public void ExecuteRule_RuleDisabled_Test()
        {
            Mock.AssignmentActionExecutorMock assignmentActionExecutorMock = new Mock.AssignmentActionExecutorMock();
            Mock.QueryActionExecutorMock queryActionExecutorMock = new Mock.QueryActionExecutorMock();

            Fake.RuleManagerFake ruleMgr = new Fake.RuleManagerFake();
            ruleMgr.AssignmentActionExecutor = assignmentActionExecutorMock;
            ruleMgr.QueryActionExecutor = queryActionExecutorMock;
            ruleMgr.mainDataSourceContent = mainDataSourceRuleConditionTrue;

            XPathNavigator nav = buildRuleNavigator(ruleDisabledManifest);
            bool actual = ruleMgr.ExecuteRule(nav);
            bool expected = false;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for ExecuteRule when the rule is enabled, condition is false.
        ///</summary>
        [TestMethod()]
        public void ExecuteRule_RuleEnabled_ConditionFalse_Test()
        {
            Mock.AssignmentActionExecutorMock assignmentActionExecutorMock = new Mock.AssignmentActionExecutorMock();
            Mock.QueryActionExecutorMock queryActionExecutorMock = new Mock.QueryActionExecutorMock();

            Fake.RuleManagerFake ruleMgr = new Fake.RuleManagerFake();
            ruleMgr.AssignmentActionExecutor = assignmentActionExecutorMock;
            ruleMgr.QueryActionExecutor = queryActionExecutorMock;
            ruleMgr.mainDataSourceContent = mainDataSourceRuleConditionFalse;

            XPathNavigator nav = buildRuleNavigator(ruleEnabledManifest);
            bool actual = ruleMgr.ExecuteRule(nav);
            bool expected = false;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for ExecuteRule when the rule is enabled, condition is true.
        ///</summary>
        [TestMethod()]
        public void ExecuteRule_RuleEnabled_ConditionTrue_Test()
        {
            Mock.AssignmentActionExecutorMock assignmentActionExecutorMock = new Mock.AssignmentActionExecutorMock();
            Mock.QueryActionExecutorMock queryActionExecutorMock = new Mock.QueryActionExecutorMock();

            Fake.RuleManagerFake ruleMgr = new Fake.RuleManagerFake();
            ruleMgr.AssignmentActionExecutor = assignmentActionExecutorMock;
            ruleMgr.QueryActionExecutor = queryActionExecutorMock;
            ruleMgr.mainDataSourceContent = mainDataSourceRuleConditionTrue;

            XPathNavigator nav = buildRuleNavigator(ruleEnabledManifest);
            bool actual = ruleMgr.ExecuteRule(nav);
            bool expected = true;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for ExecuteRule when the rule is enabled, condition is true and the condition is 'contain' condition.
        ///</summary>
        [TestMethod()]
        public void ExecuteRule_RuleEnabled_ConditionTrue_ContainCondition_Test()
        {
            Mock.AssignmentActionExecutorMock assignmentActionExecutorMock = new Mock.AssignmentActionExecutorMock();
            Mock.QueryActionExecutorMock queryActionExecutorMock = new Mock.QueryActionExecutorMock();

            Fake.RuleManagerFake ruleMgr = new Fake.RuleManagerFake();
            ruleMgr.AssignmentActionExecutor = assignmentActionExecutorMock;
            ruleMgr.QueryActionExecutor = queryActionExecutorMock;
            ruleMgr.mainDataSourceContent = mainDataSourceRuleConditionTrue;

            XPathNavigator nav = buildRuleNavigator(ruleEnabledContainConditionManifest);
            bool actual = ruleMgr.ExecuteRule(nav);
            bool expected = true;

            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///A test for ExecuteRule when the rule is enabled, condition is true and the condition is 'XPath' condition.
        ///</summary>
        [TestMethod()]
        public void ExecuteRule_RuleEnabled_ConditionTrue_XPathExpressionCondition_Test()
        {
            Mock.AssignmentActionExecutorMock assignmentActionExecutorMock = new Mock.AssignmentActionExecutorMock();
            Mock.QueryActionExecutorMock queryActionExecutorMock = new Mock.QueryActionExecutorMock();

            Fake.RuleManagerFake ruleMgr = new Fake.RuleManagerFake();
            ruleMgr.AssignmentActionExecutor = assignmentActionExecutorMock;
            ruleMgr.QueryActionExecutor = queryActionExecutorMock;
            ruleMgr.mainDataSourceContent = mainDataSourceField3EqualsField4;

            XPathNavigator nav = buildRuleNavigator(ruleEnabledXPathExpressionManifest);
            bool actual = ruleMgr.ExecuteRule(nav);
            bool expected = true;

            Assert.AreEqual(expected, actual);
        }

        #endregion

        /// <summary>
        ///A test for ExecuteAction
        ///</summary>
        [TestMethod()]
        public void ExecuteAction_AsssignmentActionTest()
        {
            Mock.AssignmentActionExecutorMock assignmentActionExecutorMock = new Mock.AssignmentActionExecutorMock();
            Mock.QueryActionExecutorMock queryActionExecutorMock = new Mock.QueryActionExecutorMock();

            Fake.RuleManagerFake ruleMgr = new Fake.RuleManagerFake();
            ruleMgr.mainDataSourceContent = mainDataSourceRuleConditionTrue;
            ruleMgr.AssignmentActionExecutor = assignmentActionExecutorMock;
            ruleMgr.QueryActionExecutor = queryActionExecutorMock;

            XPathNavigator nav = buildRuleNavigator(ruleEnabledManifest);
            
            // First child is query action, need to move to second child.
            nav.MoveToChild(XPathNodeType.Element);
            nav.MoveToNext(XPathNodeType.Element);

            ruleMgr.ExecuteAction(nav);

            string expectedNavName = nav.Name;
            string actualNavName = assignmentActionExecutorMock.actionNavigator.Name;

            Assert.AreEqual(expectedNavName, actualNavName);

            XPathNavigator actualDSNav = assignmentActionExecutorMock.dataSourceNavigatorAfterExecute;
            XmlNamespaceManager manager = new XmlNamespaceManager(actualDSNav.NameTable);
            manager.AddNamespace("my", XPathHelper.RetrieveNamespaces(actualDSNav)["my"]);
            actualDSNav = actualDSNav.SelectSingleNode("//my:field2", manager);

            string expectedValue = "test value";
            string actualValue = actualDSNav.Value;

            Assert.AreEqual(expectedValue, actualValue);

        }

        private XPathNavigator buildRuleNavigator(string manifestString)
        {
            StringReader sr = new StringReader(manifestString);
            XDocument doc = new XDocument();
            doc = XDocument.Load(sr);
            XPathNavigator nav = doc.CreateNavigator();
            nav.MoveToChild(XPathNodeType.Element);
            nav.MoveToChild(XPathNodeType.Element);
            nav.MoveToChild(XPathNodeType.Element);
            nav.MoveToChild(XPathNodeType.Element);

            return nav;
        }

        public string mainDataSourceRuleConditionFalse = @"<?xml version=""1.0""?><?mso-infoPathSolution solutionVersion=""1.0.0.9"" productVersion=""12.0.0"" PIVersion=""1.0.0.0"" href=""file:///C:\Users\v-jingym\Desktop\Template1.xsn"" name=""urn:schemas-microsoft-com:office:infopath:Template1:-myXSD-2009-12-07T03-34-57"" ?><?mso-application progid=""InfoPath.Document"" versionProgid=""InfoPath.Document.2""?><my:myFields xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xml:lang=""en-us"">
	<my:field1></my:field1>
	<my:field2>1</my:field2>
	<my:field3></my:field3>
	<my:field4></my:field4>
	<my:field5></my:field5>
</my:myFields>";

        public string mainDataSourceRuleConditionTrue = @"<?xml version=""1.0""?><?mso-infoPathSolution solutionVersion=""1.0.0.9"" productVersion=""12.0.0"" PIVersion=""1.0.0.0"" href=""file:///C:\Users\v-jingym\Desktop\Template1.xsn"" name=""urn:schemas-microsoft-com:office:infopath:Template1:-myXSD-2009-12-07T03-34-57"" ?><?mso-application progid=""InfoPath.Document"" versionProgid=""InfoPath.Document.2""?><my:myFields xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xml:lang=""en-us"">
	<my:field1></my:field1>
	<my:field2>1</my:field2>
	<my:field3>field3</my:field3>
	<my:field4>Not field4</my:field4>
	<my:field5>field5</my:field5>
</my:myFields>";

        public string mainDataSourceField3EqualsField4 = @"<?xml version=""1.0""?><?mso-infoPathSolution solutionVersion=""1.0.0.9"" productVersion=""12.0.0"" PIVersion=""1.0.0.0"" href=""file:///C:\Users\v-jingym\Desktop\Template1.xsn"" name=""urn:schemas-microsoft-com:office:infopath:Template1:-myXSD-2009-12-07T03-34-57"" ?><?mso-application progid=""InfoPath.Document"" versionProgid=""InfoPath.Document.2""?><my:myFields xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xml:lang=""en-us"">
	<my:field1></my:field1>
	<my:field2>1</my:field2>
	<my:field3>same as field3</my:field3>
	<my:field4>same as field3</my:field4>
	<my:field5>field5</my:field5>
</my:myFields>";

        public string ruleDisabledManifest = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<xsf:xDocumentClass trustSetting=""automatic"" solutionFormatVersion=""2.0.0.0"" solutionVersion=""1.0.0.10"" productVersion=""12.0.0"" name=""urn:schemas-microsoft-com:office:infopath:t1Src:-myXSD-2009-12-07T03-34-57"" xmlns:xsf=""http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"" xmlns:xsf2=""http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions"" xmlns:msxsl=""urn:schemas-microsoft-com:xslt"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xdUtil=""http://schemas.microsoft.com/office/infopath/2003/xslt/Util"" xmlns:xdXDocument=""http://schemas.microsoft.com/office/infopath/2003/xslt/xDocument"" xmlns:xdMath=""http://schemas.microsoft.com/office/infopath/2003/xslt/Math"" xmlns:xdDate=""http://schemas.microsoft.com/office/infopath/2003/xslt/Date"" xmlns:xdExtension=""http://schemas.microsoft.com/office/infopath/2003/xslt/extension"" xmlns:xdEnvironment=""http://schemas.microsoft.com/office/infopath/2006/xslt/environment"" xmlns:xdUser=""http://schemas.microsoft.com/office/infopath/2006/xslt/User"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"">
	<xsf:ruleSets>
		<xsf:ruleSet name=""ruleSet_1"">
			<xsf:rule caption=""Rule 1"" condition=""my:field3 = &quot;field3&quot; and my:field4 != &quot;field4&quot; or my:field5 = &quot;field5&quot;"" isEnabled=""no"">
				<xsf:queryAction adapter=""MCS_People""></xsf:queryAction>
				<xsf:assignmentAction targetField=""my:field2"" expression=""&quot;test value&quot;""></xsf:assignmentAction>
			</xsf:rule>
		</xsf:ruleSet>
	</xsf:ruleSets>
</xsf:xDocumentClass>
";

        public string ruleEnabledManifest = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<xsf:xDocumentClass trustSetting=""automatic"" solutionFormatVersion=""2.0.0.0"" solutionVersion=""1.0.0.10"" productVersion=""12.0.0"" name=""urn:schemas-microsoft-com:office:infopath:t1Src:-myXSD-2009-12-07T03-34-57"" xmlns:xsf=""http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"" xmlns:xsf2=""http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions"" xmlns:msxsl=""urn:schemas-microsoft-com:xslt"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xdUtil=""http://schemas.microsoft.com/office/infopath/2003/xslt/Util"" xmlns:xdXDocument=""http://schemas.microsoft.com/office/infopath/2003/xslt/xDocument"" xmlns:xdMath=""http://schemas.microsoft.com/office/infopath/2003/xslt/Math"" xmlns:xdDate=""http://schemas.microsoft.com/office/infopath/2003/xslt/Date"" xmlns:xdExtension=""http://schemas.microsoft.com/office/infopath/2003/xslt/extension"" xmlns:xdEnvironment=""http://schemas.microsoft.com/office/infopath/2006/xslt/environment"" xmlns:xdUser=""http://schemas.microsoft.com/office/infopath/2006/xslt/User"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"">
	<xsf:ruleSets>
		<xsf:ruleSet name=""ruleSet_1"">
			<xsf:rule caption=""Rule 1"" condition=""my:field3 = &quot;field3&quot; and my:field4 != &quot;field4&quot; or my:field5 = &quot;field5&quot;"" isEnabled=""yes"">
				<xsf:queryAction adapter=""MCS_People""></xsf:queryAction>
				<xsf:assignmentAction targetField=""my:field2"" expression=""&quot;test value&quot;""></xsf:assignmentAction>
			</xsf:rule>
		</xsf:ruleSet>
	</xsf:ruleSets>
</xsf:xDocumentClass>
";

        public string ruleEnabledXPathExpressionManifest = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<xsf:xDocumentClass trustSetting=""automatic"" solutionFormatVersion=""2.0.0.0"" solutionVersion=""1.0.0.10"" productVersion=""12.0.0"" name=""urn:schemas-microsoft-com:office:infopath:t1Src:-myXSD-2009-12-07T03-34-57"" xmlns:xsf=""http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"" xmlns:xsf2=""http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions"" xmlns:msxsl=""urn:schemas-microsoft-com:xslt"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xdUtil=""http://schemas.microsoft.com/office/infopath/2003/xslt/Util"" xmlns:xdXDocument=""http://schemas.microsoft.com/office/infopath/2003/xslt/xDocument"" xmlns:xdMath=""http://schemas.microsoft.com/office/infopath/2003/xslt/Math"" xmlns:xdDate=""http://schemas.microsoft.com/office/infopath/2003/xslt/Date"" xmlns:xdExtension=""http://schemas.microsoft.com/office/infopath/2003/xslt/extension"" xmlns:xdEnvironment=""http://schemas.microsoft.com/office/infopath/2006/xslt/environment"" xmlns:xdUser=""http://schemas.microsoft.com/office/infopath/2006/xslt/User"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"">
	<xsf:ruleSets>
		<xsf:ruleSet name=""ruleSet_1"">
			<xsf:rule caption=""Rule 1"" condition=""my:field3 = my:field4"" isEnabled=""yes"">
				<xsf:queryAction adapter=""MCS_People""></xsf:queryAction>
				<xsf:assignmentAction targetField=""my:field2"" expression=""&quot;test value&quot;""></xsf:assignmentAction>
			</xsf:rule>
		</xsf:ruleSet>
	</xsf:ruleSets>
</xsf:xDocumentClass>
";

        public string ruleEnabledContainConditionManifest = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<xsf:xDocumentClass trustSetting=""automatic"" solutionFormatVersion=""2.0.0.0"" solutionVersion=""1.0.0.10"" productVersion=""12.0.0"" name=""urn:schemas-microsoft-com:office:infopath:t1Src:-myXSD-2009-12-07T03-34-57"" xmlns:xsf=""http://schemas.microsoft.com/office/infopath/2003/solutionDefinition"" xmlns:xsf2=""http://schemas.microsoft.com/office/infopath/2006/solutionDefinition/extensions"" xmlns:msxsl=""urn:schemas-microsoft-com:xslt"" xmlns:xd=""http://schemas.microsoft.com/office/infopath/2003"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xdUtil=""http://schemas.microsoft.com/office/infopath/2003/xslt/Util"" xmlns:xdXDocument=""http://schemas.microsoft.com/office/infopath/2003/xslt/xDocument"" xmlns:xdMath=""http://schemas.microsoft.com/office/infopath/2003/xslt/Math"" xmlns:xdDate=""http://schemas.microsoft.com/office/infopath/2003/xslt/Date"" xmlns:xdExtension=""http://schemas.microsoft.com/office/infopath/2003/xslt/extension"" xmlns:xdEnvironment=""http://schemas.microsoft.com/office/infopath/2006/xslt/environment"" xmlns:xdUser=""http://schemas.microsoft.com/office/infopath/2006/xslt/User"" xmlns:my=""http://schemas.microsoft.com/office/infopath/2003/myXSD/2009-12-07T03:34:57"" xmlns:dfs=""http://schemas.microsoft.com/office/infopath/2003/dataFormSolution"">
	<xsf:ruleSets>
		<xsf:ruleSet name=""ruleSet_1"">
			<xsf:rule caption=""Rule 1"" condition=""contains(my:field3, &quot;field3&quot;)"" isEnabled=""yes"">
				<xsf:queryAction adapter=""MCS_People""></xsf:queryAction>
				<xsf:assignmentAction targetField=""my:field2"" expression=""&quot;test value&quot;""></xsf:assignmentAction>
			</xsf:rule>
		</xsf:ruleSet>
	</xsf:ruleSets>
</xsf:xDocumentClass>
";



    }
}
